//////////////////////////////////////////////////////////////////
// MattiseOS Kernel
// Date: 2008
// Author: Matthew Iselin
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//////////////////////////////////////////////////////////////////

#ifndef DESCRIPTORTBLS_H
#define DESCRIPTORTBLS_H

// Includes
#include <mattise.h>
#include <stdint.h>

// Structures

// an entry in the GDT
struct gdt_entry
{
	uint16_t limit_lo;				// the low word of the limit for this segment
	uint16_t base_lo;				// the low word of the base for this segment
	uint8_t base_mid;				// the low byte of the high word of the base for this segment
	uint8_t access;					// flags relating to access privileges for this segment
	uint8_t gran;					// entry granularity - used to tell the system to allow the full 4 GB address space
	uint8_t base_hi;				// the high byte of the high word of the base for this segment
} __attribute__((packed));

// the GDT pointer, used with lgdt
struct gdt_ptr
{
	uint16_t limit;					// a word that contains the size of the GDT
	uint32_t base;					// a pointer to the GDT data
} __attribute__((packed));

// an entry in the IDT
struct idt_entry
{
	uint16_t base_lo;				// the low word of the base (ie, function pointer)
	uint16_t sel;					// the code segment selector to use
	uint8_t always0;				// defined in the intel manuals as "reserved bits"
	uint8_t flags;					// flags for this entry
	uint16_t base_hi;				// the high word of the base
} __attribute__((packed));

// the IDT pointer, used with lidt
struct idt_ptr
{
	uint16_t limit;					// a word that contains the size of the IDT
	uint32_t base;					// a pointer to the IDT data
} __attribute__((packed));

// the task segment selector (TSS)
struct tss
{
    unsigned short link;
    unsigned short link_h;

    unsigned int esp0;
    unsigned short ss0;
    unsigned short ss0_h;

    unsigned int esp1;
    unsigned short ss1;
    unsigned short ss1_h;

    unsigned int esp2;
    unsigned short ss2;
    unsigned short ss2_h;

    unsigned int cr3;
    unsigned int eip;
    unsigned int eflags;

    unsigned int eax;
    unsigned int ecx;
    unsigned int edx;
    unsigned int ebx;

    unsigned int esp;
    unsigned int ebp;

    unsigned int esi;
    unsigned int edi;

    unsigned short es;
    unsigned short es_h;

    unsigned short cs;
    unsigned short cs_h;

    unsigned short ss;
    unsigned short ss_h;

    unsigned short ds;
    unsigned short ds_h;

    unsigned short fs;
    unsigned short fs_h;

    unsigned short gs;
    unsigned short gs_h;

    unsigned short ldt;
    unsigned short ldt_h;

    unsigned short trap;
    unsigned short iomap;
}__attribute((packed));

// Prototypes

// initializes the GDT
void kInitGDT();

// finishes GDT setup
void kFinishGDTSetup();

// sets a gate in the GDT
void kGdtSetGate( uint32_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran );

// initializes the IDT
void kInitIDT();

// sets a gate in the IDT
void kIdtSetGate( uint32_t num, uint32_t base, uint16_t sel, uint8_t flags );

// sets up the TSS
void kInitTSS();

// loads the TSS
void kLoadTSS();

#endif
